home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
comms
/
other
/
micq-0.4.0
/
micq.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
15KB
|
514 lines
/*********************************************
**********************************************
This is the main ICQ file. Currently it
logs in and sits in a loop. It can receive
messages and keeps the connection alive.
Use crtl-break to exit.
This software is provided AS IS to be used in
whatever way you see fit and is placed in the
public domain.
Author : Matthew Smith April 19, 1998
Contributors : Nicolas Sahlqvist April 27, 1998
Ulf Hedlund (guru@slideware.com) April 28, 1998
Michael Ivey May 4, 1998
Michael Holzt May 5, 1998
Changes :
4-28-98 support for WIN32 [UH]
4-20-98 added variable time_delay between keep_alive packets mds
4-20-98 added instant message from server support mds
4-21-98 changed so that long ( 250+ characters ) messages work
new maximum is ~900 which is hopefully big enough.
When I know more about udp maybe I can come up with
a general solution. mds I now think ICQ has a max that is
smaller than this so everything is ok mds I now think that
the icq client's maximum is arbitrary and can be ignored :)
4-23-98 Added beginnings of a user interface
4-26-98 Changed the version to 0.2a :)
4-27-98 Nicco added feature to use nick names to log in
5-05-98 Authorization Messages
5-13-98 Added time stamps for most things.
6-17-98 Changed condition on which we should send auto_reply message. Fryslan
6-18-98 Added different auto reply messages for different status types see also ui.c and util.c Fryslan
6-20-98 Added an alter command to alter your command names online. Fryslan
**********************************************
**********************************************/
#include "micq.h"
#include "datatype.h"
#include "msg_queue.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#ifdef _WIN32
#include <conio.h>
#include <io.h>
#include <winsock2.h>
#include <time.h>
#else
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/wait.h>
#include "mreadline.h"
#endif
#include <fcntl.h>
#include <time.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#ifdef __SASC
#include <proto/dos.h>
#include <proto/exec.h>
#include "amiga-dt.h"
#endif
BYTE Sound = SOUND_ON; /* Beeps on by default */
BYTE Sound_Str[150]; /* the command to run from the shell to play sound files */
BOOL Russian = FALSE; /* Do we do kio8-r <->Cp1251 codeset translation? */
BOOL Logging = TRUE; /* Do we log messages to ~/micq_log? This should probably have different levels */
BOOL Color = TRUE; /* Do we use ANSI color? */
BOOL Quit = FALSE; /* set when it's time to exit the program */
BOOL Verbose = FALSE; /* this is displays extra debuging info */
BOOL serv_mess[ 1024 ]; /* used so that we don't get duplicate messages with the same SEQ */
WORD last_cmd[ 1024 ]; /* command issued for the first 1024 SEQ #'s */
/******************** if we have more than 1024 SEQ this will need some hacking */
WORD seq_num = 1; /* current sequence number */
DWORD our_ip = 0x0100007f; /* localhost for some reason */
DWORD our_port; /* the port to make tcp connections on */
/************ We don't make tcp connections yet though :( */
DWORD UIN; /* current User Id Number */
BOOL Contact_List = FALSE; /* I think we always have a contact list now */
Contact_Member Contacts[ 100 ]; /* no more than 100 contacts max */
int Num_Contacts=0;
DWORD Current_Status=STATUS_OFFLINE;
DWORD last_recv_uin=0;
char passwd[100];
char server[100];
DWORD set_status;
DWORD remote_port;
BOOL Done_Login=FALSE;
BOOL auto_resp=FALSE;
char auto_rep_str_dnd[450] = { "Don't page me, my head is hurting!" };
char auto_rep_str_away[450] = { "I told you I wasn't here!" };
char auto_rep_str_na[450] = { "Working, working always working..." };
char auto_rep_str_occ[450] = { "I am working on opening this beer so I am busy." };
char auto_rep_str_inv[450] = { "So you can see me, so you can't!" };
char message_cmd[16];
char info_cmd[16];
char quit_cmd[16];
char reply_cmd[16];
char again_cmd[16];
char add_cmd[16];
char list_cmd[16];
char away_cmd[16];
char na_cmd[16];
char dnd_cmd[16];
char online_cmd[16];
char occ_cmd[16];
char ffc_cmd[16];
char inv_cmd[16];
char status_cmd[16];
char auth_cmd[16];
char auto_cmd[16];
char change_cmd[16];
char search_cmd[16];
char save_cmd[16];
char alter_cmd[16];
char msga_cmd[16];
char url_cmd[16];
char update_cmd[16];
char rand_cmd[16];
char color_cmd[16];
char sound_cmd[16];
/*** auto away values ***/
int idle_val=0;
int idle_flag=0;
#define away_time 600
unsigned int next_resend;
/*/////////////////////////////////////////////
// Connects to hostname on port port
// hostname can be DNS or nnn.nnn.nnn.nnn
// write out messages to the FD aux */
int Connect_Remote( char *hostname, int port, FD_T aux )
{
int conct, length;
int sok;
struct sockaddr_in sin; /* used to store inet addr stuff */
struct hostent *host_struct; /* used in DNS lookup */
#if 1
sin.sin_addr.s_addr = inet_addr( hostname );
if ( sin.sin_addr.s_addr == -1 ) /* name isn't n.n.n.n so must be DNS */
#else
if ( inet_aton( hostname, &sin.sin_addr ) == 0 ) /* checks for n.n.n.n notation */
#endif
{
host_struct = gethostbyname( hostname );/* name isn't n.n.n.n so must be DNS */
if ( host_struct == NULL )
{
if ( Verbose )
{
M_fdprint( aux, "Shakespeare couldn't spell why should I?\n" );
M_fdprint( aux, " Especially something like %s\n", hostname );
/*herror( "Can't find hostname" );*/
}
return 0;
}
sin.sin_addr = *((struct in_addr *)host_struct->h_addr);
}
sin.sin_family = AF_INET; /* we're using the inet not appletalk*/
sin.sin_port = htons( port ); /* port */
sok = socket( AF_INET, SOCK_DGRAM, 0 );/* create the unconnected socket*/
if ( sok == -1 )
{
perror( "Socket creation failed" );
exit( 1 );
}
if ( Verbose )
{
M_fdprint( aux, "Socket created attempting to connect\n" );
}
conct = connect( sok, (struct sockaddr *) &sin, sizeof( sin ) );
if ( conct == -1 )/* did we connect ?*/
{
if ( Verbose )
{
M_fdprint( aux, " Conection Refused on port %d at %s\n", port, hostname );
#ifdef FUNNY_MSGS
M_fdprint( aux, " D'oh!\n" );
#endif
perror( "connect" );
}
return 0;
}
length = sizeof( sin ) ;
getsockname( sok, (struct sockaddr *) &sin, &length );
our_ip = sin.sin_addr.s_addr;
our_port = sin.sin_port;
if (Verbose )
{
#ifdef FUNNY_MSGS
M_fdprint( aux, "Our port is %d, take her to sea Mr. Mordoch.\n", ntohs( sin.sin_port ) );
#else
M_fdprint( aux, "The port that will be used for tcp ( not yet implemented ) is %d\n", ntohs( sin.sin_port ) );
#endif
}
if ( Verbose )
{
M_fdprint( aux, "Connected to %s, waiting for response\n", hostname );
}
return sok;
}
/******************************************
Handles packets that the server sends to us.
*******************************************/
void Handle_Server_Response( SOK_T sok )
{
srv_net_icq_pak pak;
static DWORD last_seq=-1;
int s;
s = SOCKREAD( sok, &pak.head.ver, sizeof( pak ) - 2 );
if ( s < 0 )
return;
#if 0
M_print( "Cmd : %04X\t",Chars_2_Word( pak.head.cmd ) );
M_print( "Ver : %04X\t",Chars_2_Word( pak.head.ver ) );
M_print( "Seq : %08X\t",Chars_2_DW( pak.head.seq ) );
M_print( "Ses : %08X\n",Chars_2_DW( pak.head.session ) );
#endif
if ( Chars_2_DW( pak.head.session ) != our_session ) {
if ( Verbose ) {
R_undraw();
M_print( "Got a bad session ID %08X with CMD %04X ignored.\n",
Chars_2_DW( pak.head.session ), Chars_2_Word( pak.head.cmd ) );
R_redraw();
}
return;
}
/* !!! TODO make a check checksum routine to verify the packet further */
/* if ( ( serv_mess[ Chars_2_Word( pak.head.seq2 ) ] ) &&
( Chars_2_Word( pak.head.cmd ) != SRV_NEW_UIN ) )*/
if ( ( last_seq == Char